package com.hongbao.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 作者: LCG
 * 日期: 2020/1/31 15:46
 * 描述: 这是个红包的工具类，支持整数的红包个数和整数的单个红包的值
 */
public class HongBaoUtils {

    /**
     * 每个红包最小金额
     */
    private static final int MIN_MONEY = 1;

    /**
     * 红包金额的离散程度，值越大红包金额越分散
     */
    private static final double DISPERSE = 4;

    /**
     * 根据剩余的红包金额和红包个数，获取一个红包的金额，这个金额是一个整数
     * @return 返回红包的值
     */
    public static BigDecimal getOneRedBag(RedPackage2 redpackage) {


        int money = redpackage.getMoney().setScale(2, RoundingMode.HALF_UP).multiply(new BigDecimal(1)).intValue();

        //红包数和总金额都是0的情况下返回0
        if(redpackage.getMoney().compareTo(new BigDecimal(0))==0&&redpackage.getCount()==0){
           return new BigDecimal(0);
        }
        //剩余的红包个数是1的时候直接返回剩余的所有金额
        if(redpackage.getCount()==1){
            BigDecimal money1 = redpackage.getMoney();
            redpackage.setCount(0);
            redpackage.setMoney(new BigDecimal(0));
            return money1;
        }

        if (money / redpackage.getCount() < MIN_MONEY) {
            throw new RuntimeException("最小值设置过大");
        }

        //最大值 = 均值*离散程度
        int max = (int) (money * DISPERSE / redpackage.getCount());

        //最大值不能大于总金额
        max = max > money ? money : max;

        BigDecimal divide = new BigDecimal(randomBetweenMinAndMax(money, redpackage.getCount(), MIN_MONEY, max)).divide(new BigDecimal(1), 0,
                RoundingMode.HALF_UP);

        redpackage.setCount(redpackage.getCount()-1);
        redpackage.setMoney(redpackage.getMoney().subtract(divide));

        return divide;

    }

    /**
     * 在最小值和最大值之间随机产生一个红包
     * @param money
     * @param count
     * @param min : 最小金额
     * @param max ： 最大金额
     * @return
     */
    private static int randomBetweenMinAndMax(int money, int count, int min, int max) {
        //最后一个红包直接返回
        if (count == 1) {
            return money;
        }
        //最小和最大金额一样，返最小和最大值都行
        if (min == max) {
            return min;
        }
        //最小值 == 均值， 直接返回最小值
        if (min == money / count) {
            return min;
        }
        //min<=随机数bag<=max
        int bag = ((int) Math.rint(Math.random() * (max - min) + min));

        //剩余的均值
        int avg = (money - bag) / (count - 1);
        //比较验证剩余的红包还够不够分(均值>=最小值 是必须条件),不够分的话就是最大值过大
        if (avg < MIN_MONEY) {
            /*
             * 重新随机一个红包，最大值改成本次生成的红包金额
             * 由于 min<=本次红包金额bag<=max, 所以递归时bag是不断减小的。
             * bag在减小到min之间一定有一个值是合适的，递归结束。
             * bag减小到和min相等时，递归也会结束，所以这里不会死递归。
             */
            return randomBetweenMinAndMax(money, count, min, bag);
        } else {
            return bag;
        }
    }



}
